#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "gprs.h"
#include "platform.h"
#include "circle_buffer.h"


typedef struct 
{
	sj_int8 fd;
	sj_int8 inited;
	volatile sj_int8 cmd;
	circle_buffer_info circle_info;
	sj_event *sem;
}gprs_private_data;

static gprs_private_data gs_private_data={0};
static gprs_private_data* gs_data=&gs_private_data;



static sj_void gprs_read_task_func(sj_void *arg)
{
	char buffer[128]={0};
	int len=0,i,index=0,ret=0;
	if(sj_platform_device_poll(gs_data->fd,-1)>0)
	{
		while(1)
		{
			ret = sj_platform_device_read(gs_data->fd,buffer,128);
            if(ret<=0)
            {
            	break;
            }else{
    //         	for(i =0 ;i<ret;i++)
				// {
				// 	if(buffer[i]=='\r'|| buffer[i]=='\n')
				// 	{
				// 		printf("%02x ",buffer[i]);
				// 	}
				// 	else
				// 	{
				// 		printf("%c ",buffer[i]);
				// 	}
				// }
				// printf("\n******\n");
            	circle_buffer_write(&gs_data->circle_info,buffer,ret);
            }      
	    }	
	}
	len = circle_buffer_get_num(&gs_data->circle_info);

	if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\nRDY\r\n",strlen("\r\nRDY\r\n"))))
	{
		ret = circle_buffer_set_read(&gs_data->circle_info,index);
		printf("ready \n");	
		
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\nOK\r\n",strlen("\r\nOK\r\n"))))
	{
		printf("ok\n");
		circle_buffer_set_read(&gs_data->circle_info,index);
		//sj_sem_post(gs_data->sem);
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\nERROR\r\n",strlen("\r\nERROR\r\n"))))
	{
		printf("err\n");
		circle_buffer_set_read(&gs_data->circle_info,index);
		//sj_sem_post(gs_data->sem);
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\n+QIOPEN: ",strlen("\r\n+QIOPEN: "))))
	{
		int rn_index=0;
		if((rn_index = find_str(gs_data->circle_info.item_ptr,index,len-index+gs_data->circle_info.read,"\r\n",strlen("\r\n"))))
		{
			int comma_index=find_str(gs_data->circle_info.item_ptr,index,len-index+gs_data->circle_info.read,",",strlen(","));
			char chn = -1;
			char err = -1;
			if(comma_index - index==3)
			{
				chn = (*(char *)(gs_data->circle_info.item_ptr+index) - 0x30)*10 +(*(char *)(gs_data->circle_info.item_ptr+index+1)-0x30);

				err = (*(char *)(gs_data->circle_info.item_ptr+comma_index)-0x30);
			}
			else if(comma_index - index==2)
			{
				chn = (*(char *)(gs_data->circle_info.item_ptr+index)-0x30);
				err = (*(char *)(gs_data->circle_info.item_ptr+comma_index)-0x30);				
			}
			printf("chn %d err %d \n",chn,err);
			circle_buffer_set_read(&gs_data->circle_info,rn_index);
		}
		//sj_sem_post(gs_data->sem);		
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\n+QIURC: \"closed\",",strlen("\r\n+QIURC: \"closed\","))))
	{
		int rn_index=0;
		if((rn_index = find_str(gs_data->circle_info.item_ptr,index,len-index+gs_data->circle_info.read,"\r\n",strlen("\r\n"))))
		{
			printf("chn %d closed\n",atoi((char *)(gs_data->circle_info.item_ptr+index)));
			circle_buffer_set_read(&gs_data->circle_info,rn_index);
		}	
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\n+QISTATE: ",strlen("\r\n+QISTATE: "))))
	{
		int rn_index=0;
		if((rn_index = find_str(gs_data->circle_info.item_ptr,index,len-index+gs_data->circle_info.read,"\r\n\r\nOK\r\n",strlen("\r\n\r\nOK\r\n"))))
		{
			printf("%s\n",gs_data->circle_info.item_ptr);
			circle_buffer_set_read(&gs_data->circle_info,rn_index);			
		}	
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\n+CSQ: ",strlen("\r\n+CSQ: "))))
	{
		int rn_index=0;
		if((rn_index = find_str(gs_data->circle_info.item_ptr,index,len-index+gs_data->circle_info.read,"\r\n\r\nOK\r\n",strlen("\r\n\r\nOK\r\n"))))
		{
			printf("%s\n",gs_data->circle_info.item_ptr);
			circle_buffer_set_read(&gs_data->circle_info,rn_index);			
		}	
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\n+QCCID: ",strlen("\r\n+QCCID: "))))
	{
		int rn_index=0;
		if((rn_index = find_str(gs_data->circle_info.item_ptr,index,len-index+gs_data->circle_info.read,"\r\n\r\nOK\r\n",strlen("\r\n\r\nOK\r\n"))))
		{
			printf("%s\n",gs_data->circle_info.item_ptr);
			circle_buffer_set_read(&gs_data->circle_info,rn_index);			
		}	
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\n+QCCID: ",strlen("\r\n+QCCID: "))))
	{
		int rn_index=0;
		if((rn_index = find_str(gs_data->circle_info.item_ptr,index,len-index+gs_data->circle_info.read,"\r\n\r\nOK\r\n",strlen("\r\n\r\nOK\r\n"))))
		{
			printf("%s\n",gs_data->circle_info.item_ptr);
			circle_buffer_set_read(&gs_data->circle_info,rn_index);			
		}	
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\n>",strlen("\r\n>"))))
	{
		circle_buffer_set_read(&gs_data->circle_info,index);	
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\nSEND OK\r\n",strlen("\r\nSEND OK\r\n"))))
	{
		printf("%s\n",gs_data->circle_info.item_ptr);
		circle_buffer_set_read(&gs_data->circle_info,index);	
	}
	else if((index = find_str(gs_data->circle_info.item_ptr,gs_data->circle_info.read,len,"\r\nSEND FAIL\r\n",strlen("\r\nSEND FAIL\r\n"))))
	{
		printf("%s\n",gs_data->circle_info.item_ptr);
		circle_buffer_set_read(&gs_data->circle_info,index);	
	}

	if(circle_buffer_is_empty(&gs_data->circle_info))
	{
		printf("clear\n");
		circle_buffer_clear(&gs_data->circle_info);
	}	
}


static sj_void gprs_read_init(sj_void)
{
	
	gs_data->sem = sj_sem_create(0);

	circle_buffer_create(&gs_data->circle_info,1, 1024);
}

static sj_void gprs_task_func(sj_void *arg)
{

}

static sj_void gprs_init(sj_void)
{
	gs_data->fd = sj_platform_device_open("/dev/ttyAMA4",0);

	sj_platform_device_write(gs_data->fd,(sj_uchar*)"ATE0\r\n",strlen("ATE0\r\n"));
	
	sj_task_resume(get_gprs_read_task_handle(),0);

	if(gs_data->fd>0)
	{
		gs_data->inited =1;
	}
}


sj_int8 gprs_sync_send_cmd(gprs_link_handle *handle,sj_int8 cmd,gprs_cmd_data *data,sj_int32 timeout)
{
	sj_int8 ret = 0;
	sj_int8 sem_ret=0;
	sj_char atcmd[64]={0};
	sj_char *write_buf=atcmd;
	sj_int32 lenght=0;
	if(gs_data->fd<=0)
	{
		ret =-1;
		goto out;
	}
	switch(cmd)
	{
		case GPRS_CMD_SET_ATE0:
			sprintf(atcmd,"ATE0\r\n");
			lenght =strlen(atcmd);
			break;
		case GPRS_CMD_GET_CSQ:
			sprintf(atcmd,"AT+CSQ\r\n");
			lenght =strlen(atcmd);
			break;
		case GPRS_CMD_GET_ICCID:
			sprintf(atcmd,"AT+QCCID\r\n");
			lenght =strlen(atcmd);
			break;
		case GPRS_CMD_GET_IMEI:
			sprintf(atcmd,"AT+CGSN\r\n");
			lenght =strlen(atcmd);
			break;

		case GPRS_CMD_SET_CSGP_DEFAULT:	
			sprintf(atcmd,"AT+QICSGP=1,1,\"UNINET\",\"\",\"\",1\r\n");	
			lenght =strlen(atcmd);	
			break;

		case GPRS_CMD_SET_CSGP:
			sprintf(atcmd,"AT+QICSGP=%d,%d,\"%s\",\"\",\"\",1\r\n",
				data->gsgp.context_id,data->gsgp.connect_type,data->gsgp.apn);	
			lenght =strlen(atcmd);		
			break;

		case GPRS_CMD_SOCKET_STATE:
			sprintf(atcmd,"AT+QISTATE=%d,%d\r\n",handle->context_id,handle->connect_id);
			lenght =strlen(atcmd);
			break;

		case GPRS_CMD_SOCKET_OPEN:
			sprintf(atcmd,"AT+QIOPEN=%d,%d,\"%s\",\"%s\",%d,%d,%d\r\n",
				handle->context_id,handle->connect_id,handle->service_type,handle->ip_addr,handle->remote_port,
				handle->local_port,handle->access_mode);
			lenght =strlen(atcmd);
			break;

		case GPRS_CMD_SOCKET_SEND_DATA:
			sprintf(atcmd,"AT+QISEND=%d,%d\r\n",handle->connect_id,data->data.lenght);
			lenght =strlen(atcmd);
			printf("atcmd %s",atcmd);
			ret = sj_platform_device_write(gs_data->fd,(sj_uchar*)atcmd,lenght);	
			if(ret>0)
			{
				sem_ret = sj_sem_wait(gs_data->sem,timeout);
				printf("sem_ret %d \n",sem_ret);
				write_buf = data->data.data;
				lenght	  = data->data.lenght;
				printf("%s",write_buf);
			}
			else
			{
				goto out;
			}
			break;

		case GPRS_CMD_SOCKET_CLOSE:
			sprintf(atcmd,"AT+QICLOSE=%d\r\n",handle->connect_id);
			lenght =strlen(atcmd);
			break;

		default:
			break;
	}
	ret = sj_platform_device_write(gs_data->fd,(sj_uchar*)write_buf,lenght);
	if(ret>0)
	{
		sem_ret = sj_sem_wait(gs_data->sem,timeout);
		printf("sem_ret %d \n",sem_ret);
	}

	out:
	return ret;
}

sj_int8 gprs_async_send_cmd(gprs_link_handle *handle,sj_int8 cmd)
{
	sj_int8 ret = 0;
	if(gs_data->fd<=0)
	{
		ret =-1;
		goto out;
	}

	out:
	return ret;
}








static sj_task_t gprs_task ={
					.taskid=0,
					.name="gprs_task",
					.init_func=gprs_init,
					.run_func=gprs_task_func,
					.exit_func=NULL,
					.task={.inited=0,.exit =0,.status=0,.periodtime=-1,.private_ptr=NULL,}
					};


static sj_task_t gprs_read_task ={
					.taskid=0,
					.name="gprs_read_task",
					.init_func=gprs_read_init,
					.run_func=gprs_read_task_func,
					.exit_func=NULL,
					.task={.inited=0,.exit =0,.status=0,.periodtime=-1,.private_ptr=NULL,}
					};

sj_task_t *get_gprs_read_task_handle(sj_void)
{
	return &gprs_read_task;
}

sj_task_t *get_gprs_task_handle(sj_void)
{
	return &gprs_task;
}